package org.monkey.common.gateway.config;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;

@Slf4j
@Component
@Primary
public class SwaggerResourceConfig implements SwaggerResourcesProvider {

  public static final String SWAGGER2URL = "/v2/api-docs";
  private static final String prefix = "ReactiveCompositeDiscoveryClient_";
  /**
   * 使用动态路由，获取到指定的路由规则
   */
  @Autowired
  RouteLocator routeLocator;

  /**
   * 聚合其他服务接口
   *
   * @return java.util.List<springfox.documentation.swagger.web.SwaggerResource>
   * @author llxiao
   * @date 2022/3/30
   */
  @Override
  public List<SwaggerResource> get() {
    // swagger api resource list
    List<SwaggerResource> resourceList = new ArrayList<>();
    // router's host list
    Set<String> routeHosts = new HashSet<>();
    // route repeat set
    Set<String> existsServer = new HashSet<>();
    // get routers
    Flux<Route> routeFlux = routeLocator.getRoutes();
    routeFlux.subscribe(
        route -> {
          String host = route.getUri().getHost();
          if (!routeHosts.contains(host)) {
            //use routes meta data to add api group
            String groupStr = route.getMetadata().getOrDefault("swaggerGroups", "").toString();
            if (StrUtil.isNotBlank(groupStr)) {
              List<String> groupNames = StrUtil.split(groupStr, ";");
              for (String group : groupNames) {
                String url = "/" + host + SWAGGER2URL + "?group=" + group;
                routeHosts.add(host);
                if (!existsServer.contains(url)) {
                  existsServer.add(url);
                  SwaggerResource swaggerResource = new SwaggerResource();
                  swaggerResource.setUrl(url);
                  swaggerResource.setName(group);
                  resourceList.add(swaggerResource);
                }
              }
            }else{
              routeHosts.add(host);
              String url = "/" + host + SWAGGER2URL;
              if (!existsServer.contains(url)) {
                existsServer.add(url);
                SwaggerResource swaggerResource = new SwaggerResource();
                swaggerResource.setUrl(url);
                String name = route.getId();
                if(name.startsWith(prefix)){
                  name = name.substring(prefix.length());
                }
                swaggerResource.setName(name);
                resourceList.add(swaggerResource);
              }
            }
          }
        });
    log.info("网关服务地址列表：{}", JSONUtil.toJsonStr(routeHosts));
    log.info("开放的服务：{}", JSONUtil.toJsonStr(existsServer));
    return resourceList;
  }
}
